import java.util.ArrayList;
import java.util.Random;


public class Battle {

	private ArrayList<Player> sortedPeeps;
	private ArrayList<Player> baddies;
	private ArrayList<Action> actions;
	private int curIndex;
	private Player[] target;
	private Action action;
	private String curAction;
	private Random r;
	private int lastCrit;
	private int[] statsIfLevel;
	public Battle( ArrayList<Player> good,  ArrayList<Player> bad, ArrayList<Action> actions){
		this.actions = actions;
		r = new Random();
		baddies = new ArrayList<Player>();
		for(int i = 0; i < bad.size(); i++){
			baddies.add(bad.get(i));
		}
		ArrayList<Player> all = new ArrayList<Player>(good);
		all.addAll(bad);
		sortedPeeps = getFastest(all);
		curIndex = -1;
		lastCrit = 0;
		statsIfLevel = new int[]{1, 0, 0, 0, 0, 0, 0}; //hp mp def mdef str int speed
		for(int i = 0; i < 6; i++){
			statsIfLevel[r.nextInt(statsIfLevel.length)] += 1;
		}
	}

	public ArrayList<Player> getBaddies(){
		return baddies;
	}

	public String descEnemies(){
		return baddies.size() + " " + baddies.get(0).getName() + (baddies.size() > 1 ? "s" : "");
	}

	public Battle(ArrayList<Player> p){
		sortedPeeps = new ArrayList<Player>(getFastest(p));
	}

	/**
	 * Takes an arrayList and orders by speed.
	 * 
	 * @param peeps (the people you wanted sorted)
	 * @return An ArrayList of peeps sorted.
	 */
	private ArrayList<Player> getFastest(ArrayList<Player> peeps){
		boolean change = false;
		for(int i = 1; i < peeps.size(); i++){
			if(peeps.get(i).getSpeed() > peeps.get(i - 1).getSpeed()){
				change = true;
				Player temp = peeps.get(i);
				peeps.set(i, peeps.get(i - 1));
				peeps.set(i - 1, temp);
			}
		}
		if(!change)
			return peeps;
		else
			return getFastest(peeps);
	}

	public Player currentTurn(){
		return sortedPeeps.get(curIndex);
	}

	public boolean nextTurn(){
		lastCrit = 0;
		if(curIndex == -1)
			sortedPeeps = this.getFastest(sortedPeeps);
		curIndex++;
		if(curIndex >= sortedPeeps.size())
			return false;
		if(sortedPeeps.get(curIndex).getName().equals("Maleable Man"))
			curAction = action.getName();
		else{
			curAction = randEnemyAction(sortedPeeps.get(curIndex));
		}
		return true;
	}

	public void recycle(){
		curIndex = -1;
	}

	private String randEnemyAction(Player player) {
		int curMp = player.getCurMp();
		String action = "";
		int cost = player.getMp() + 1;
		while(cost > curMp){
			action = player.getActions().get(r.nextInt(player.getActions().size()));
			cost = Utilities.findSomething(action, actions).getManaCost();
		}
		return action;
	}

	public boolean wasLastCrit(){
		return lastCrit == 1;
	}

	public int processCommand(String com, Player cast, Player target){
		int ret = 0;
		if(com.startsWith("damage")){
			double percent = Double.parseDouble(com.substring(com.indexOf(" ") + 1)) / 100.0;
			if(lastCrit == 0){
				int crit = r.nextInt(100);
				if(crit < 15)
					lastCrit = 1;
				else
					lastCrit = -1;
			}
			double atk = ((cast.getStr() * (lastCrit == 1.0 ? 1.5 : 1.0))* percent);
			int dmg = Math.max((int) atk - target.getDef(), 1);
			ret = dmg;
		}
		else if(com.startsWith("mdamage")){
			double percent = Integer.parseInt(com.substring(com.indexOf(" ") + 1)) / 100;
			double atk = (cast.getInt() * percent);
			int dmg = Math.max((int) atk - target.getMdef(), 1);
			ret = dmg;
		}
		else if(com.startsWith("recover")){
			int curHp = target.getCurHp();
			int hp = target.getHp(); 
			int healed = Integer.parseInt(com.substring(com.indexOf(" ") + 1));
			if(hp - curHp < healed)
				healed = hp - curHp;
			ret = healed;
		}
		else if(com.startsWith("replenish")){
			int curMp = target.getCurMp();
			int mp = target.getMp();
			int healed = Integer.parseInt(com.substring(com.indexOf(" ") + 1));
			if(mp - curMp < healed)
				healed = mp - curMp;
			ret = healed;
		}
		else if(com.startsWith("run")){
			int chance = r.nextInt(100);
			int avgLevel = 0;
			for(int i = 0; i < baddies.size(); i++){
				avgLevel += baddies.get(i).getLevel();
			}
			avgLevel /= 3;
			int base = 50 + ((target.getLevel() - avgLevel) * 10);
			if(chance < base)
				ret = 1;
			else
				ret = 0;
		}
		return ret;
	}

	public int numEnemiesAlive(){
		int count = 0;
		for(int i = 0; i < baddies.size(); i++){
			if(baddies.get(i).getCurHp() > 0)
				count++;
		}
		return count;
	}

	public void setTarget(Player[] p){
		target = p;
	}
	public Player[] getTarget(){
		return target;
	}
	public void setAction(Action action){
		this.action = action;
	}
	public Action playerAction(){
		return action;
	}
	public String currentAction(){
		return curAction;
	}
	public int getGoldWon(){
		int gold = 0;
		for(int i = 0; i < baddies.size(); i++)
			gold += baddies.get(i).getGold();
		return gold;
	}
	public int getExpWon(){
		int exp = 0;
		for(int i = 0; i < baddies.size(); i++)
			exp += baddies.get(i).getExp();
		return exp;
	}
	
	public int[] statRaiseIfLevel(){
		return statsIfLevel;
	}
}
